<?php
/**
 * @file
 * @author Anthony Free
 * @package fwork
 * @subpackage utilities
 * @version 20111002
 */

/**
 * Base Class for Singletons
 * Use Singleton::CreateInstance('[CLASSNAME]'); to make a Singleton of a class
 * @author Anthony Free
 * @package fwork
 * @subpackage utilities
 * @version 20111002
 */
class Singleton {
	/**
	 * Array to hold Instances of the Instanciated Singletons
	 * @static $gInstances
	 * @var Array $gInstances
	 */
    private static $gInstances = array();


	/**
	 * Constructor to be inherited for the Singleton class
	 */
    protected function SingletonConstruct() {}

    /**
	 * This method cannot be overriden, use "SingletonConstruct" as your constructor
	 * @final __construct()
	 */
    final private function __construct() {}
    /**
	 * Create an Instance of a Singleton
	 * @static CreateInstance
	 * @final CreateInstance
	 * @param String $ClassName
	 * @throws InvalidUseOfSingletonException
	 * @return Class
	 */
    final public static function CreateInstance( $ClassName ) {
        if( !array_key_exists( $ClassName, self::$gInstances ) ) {
            self::$gInstances[$ClassName] = new $ClassName;

            // Check we are a singleton inheritant
            if( !( self::$gInstances[$ClassName] instanceof Singleton ) ) {
                unset( self::$gInstances[$ClassName] );
                throw new InvalidUseOfSingletonException( "$inClass is not a Singleton class." );
            }
            self::$gInstances[$ClassName]->SingletonConstruct();
        }

        $theInstance =& self::$gInstances[$ClassName];
        return $theInstance;
    }
    /**
	 * @final __clone()
	 * @throws InvalidUseOfSingletonException
	 */
    final private function __clone() {
		throw new InvalidUseOfSingletonException( "No Cloning Of Singletons is permitted");
	}
	/**
	 * @final __clone()
	 * @throws InvalidUseOfSingletonException
	 */
	final private function __wakeup() {
		throw new InvalidUseOfSingletonException( "No Unserialising of Singletons is permitted");
	}
}
?>